package cmich.cps.scheduler.algorithms;

import java.util.ArrayList;
import java.util.List;

import cmich.cps.scheduler.data.Preference;
import cmich.cps.scheduler.data.Professor;

/**
 * The Class SuperHybrid.
 * 
 * @author Jonathan Kissinger <kissi1j@cmich.edu>
 */
public class SuperHybrid extends Algorithm {
	
	/** Are we operating in super fast mode. */
	private boolean isSuperFastMode = true;

	/* (non-Javadoc)
	 * @see cmich.cps.scheduler.algorithms.Algorithm#start()
	 */
	@Override
	public void start() {
		LOGGER.fine("Starting Hybrid schedule generation algorithm.");
		max = getTheoreticalMax();
		algorithmName = "Super Hybrid";
		int value = 0;
		this.isFastMode = setIsFastMode();
		while(counter==0 && value<max && !isCancelled()) {
			counter = seed;
			LOGGER.fine("Generating schedule (" + seed + ") with Super Hybrid algorithm.");
			system.resetVariables();
			generateSchedule();
			if(validator.postValidate(schedule) && (bestSchedule==null || bestSchedule.getValue()<schedule.getValue())) {
				bestSchedule = schedule;
				value = bestSchedule.getValue();
				LOGGER.config("New highest value schedule found, value: " + value);
			}
			seed++;
		}
		LOGGER.fine("Done generating schedules with hybrid algorithm.");
	}

	/* (non-Javadoc)
	 * @see cmich.cps.scheduler.algorithms.Algorithm#overallTiebreaker(java.util.List)
	 */
	@Override
	protected Preference overallTiebreaker(List<Preference> ties) {
		ties = filterByNewProfessors(ties);
		ties = filterByTimeBetweenCourses(ties);
		ties = filterByProfessorsWithHalfMax(ties);
		ties = filterByNewCourses(ties);
		ties = filterBySpecificRoomCourses(ties);
		LOGGER.finer("Still a " + ties.size() + " way tie");
		return getNextTie(ties);
	}

	/* (non-Javadoc)
	 * @see cmich.cps.scheduler.algorithms.Algorithm#courseTiebreaker(java.util.List)
	 */
	@Override
	protected Preference courseTiebreaker(List<Preference> ties) {
		ties = filterByNewProfessors(ties);
		ties = filterByTimeBetweenCourses(ties);
		ties = filterByProfessorsWithHalfMax(ties);
		ties = filterByNewCoursesForProfessor(ties);
		if(isSuperFastMode) {
			if(ties.size()>0) return ties.get(0);
			else return null;
		}
		return getNextTie(ties);
	}

	/* (non-Javadoc)
	 * @see cmich.cps.scheduler.algorithms.Algorithm#professorTiebreaker(cmich.cps.scheduler.data.Professor, java.util.List)
	 */
	@Override
	protected Preference professorTiebreaker(Professor professor, List<Preference> ties) {
		List<Preference> preferences = new ArrayList<Preference>();
		if(!professor.getTimeBetweenCourses().equals("No preference")) {
			for(int i=0;i<ties.size();i++) {
				String timeslot = ties.get(i).getItem().split("::")[1];
				if(isOptimalTimeslot(timeslot, professor.getTimeBetweenCourses())) {
					preferences.add(ties.get(i));
				}
			}
		}
		if(preferences.size()>0) {
			ties = preferences;
		}
		if(isSuperFastMode || isFastMode) {
			if(ties.size()==0) {
				return null;
			}
			return ties.get(0);
		}
		return getNextTie(ties);
	}
}